package com.mastercard.assets.web.struts.actions;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.mastercard.assets.MasterCardException;
import com.mastercard.assets.jpa.TblAsset;
import com.mastercard.assets.jpa.TblCategoria;
import com.mastercard.assets.jpa.TblCuenta;
import com.mastercard.assets.jpa.TblCuentaPaquete;
import com.mastercard.assets.jpa.TblPaquete;
import com.mastercard.assets.jpa.TblSubcateg;
import com.mastercard.assets.jpa.TblTipoCuenta;
import com.mastercard.assets.jpa.TblTipoCuentaPaquete;
import com.mastercard.assets.notifications.NotificationUtil;
import com.mastercard.assets.util.MCUtil;
import com.mastercard.assets.util.dao.MasterCardDAO;
import com.mastercard.assets.web.struts.forms.AssetAltaForm;
import com.mastercard.assets.web.struts.forms.AssetAsignarPaquetesForm;
import com.mastercard.assets.web.struts.forms.AssetBorrarForm;
import com.mastercard.assets.web.struts.forms.AssetBuscarForm;
import com.mastercard.assets.web.struts.forms.AssetEditarForm;
import com.mastercard.assets.web.struts.forms.AssetModificarPaquetesForm;
import com.mastercard.assets.web.struts.forms.LoginForm;
import com.mastercard.assets.web.struts.forms.SolicitarPaqueteRegistrarForm;
import com.mastercard.assets.web.util.to.PaqueteSolicitar;
import com.mastercard.assets.web.util.to.UserLogin;

public class SolicitarPaqueteRegistrar
	extends
		Action
{
	public ActionForward execute(
							ActionMapping mapping , 
							ActionForm form ,
							HttpServletRequest request , 
							HttpServletResponse response )
		throws 
			IOException , 
			ServletException
	{
		HttpSession session = request.getSession( ) ;
		
		// en caos de null
		if( session == null )
			return mapping.findForward( "noLogin" ) ;
		
		// toma el userLogin
		UserLogin user = ( UserLogin ) session.getAttribute( "UserLogin" ) ;
		
		// en caso de null
		if( user == null )
			return mapping.findForward( "noLogin" ) ;
		
		// toma el form
		SolicitarPaqueteRegistrarForm f = ( SolicitarPaqueteRegistrarForm ) form ;
		
		// toma los paquetes solicitados y los regresados
		int[ ] solicitados = f.getAsignarInt( ) ;
		int[ ] regresados = f.getRegresarInt( ) ;
		
		// toma los paquetes a solicitar
		List< PaqueteSolicitar > paqueteSolicitarLista = f.getPackageManager( ).getPaqueteSolicitarLista( ) ;
		
		System.out.println( solicitados.length + " - " + regresados.length + " - " + paqueteSolicitarLista.size( ) ) ;
		
		int paqueteSolicitarListaSize = paqueteSolicitarLista.size( ) ;
		
		// recorre los PaqueteSolicitar para procesar los regresados
		for( int i = 0 ; i < paqueteSolicitarListaSize ; i++ )
		{
			// verifica que haya regresados
			if( regresados[ i ] < 1 )
				// siuiente
				continue ;
			
			PaqueteSolicitar paqSol = paqueteSolicitarLista.get( i ) ;
			
			// datos
			// toma la cuenta
			int cveCuenta = paqSol.getCveCuenta( ) ;
			TblCuenta cuenta = MasterCardDAO.findCountById( cveCuenta ) ;
			
			TblAsset evento = paqSol.getEvento( ) ;
			int habitacion = paqSol.getTipoHabitacion( ) ;
			
			// en caos de null
			if( cuenta == null )
			{
				user.setMessageError( MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.tipocuenta.solicitarpaquetes.CountNotExist" ) ) ;
				
				user.setNextWorkArea( "/WEB-INF/pages/WorkArea/SolicitarPaqueteError.jsp" ) ;
				
                                MasterCardDAO.closeEntityManager( ) ;
				return mapping.findForward( "success" ) ;
			}
			
			// toma los paquetes de dicha cuenta
			List< TblCuentaPaquete > paquetesEnCuenta = cuenta.getTblCuentaPaquetes( ) ;
			
//			List< TblCuentaPaquete > paquetesAsignados = new ArrayList< TblCuentaPaquete >( ) ;
			List< TblCuentaPaquete > paquetesAsignados = paqSol.getPaquetesAsignadosACuenta( ) ;
			
			// recorre los paquetes
//			for( TblCuentaPaquete paqueteEnCuenta : paquetesEnCuenta )
//			{
//				// en caos de que el paquete coincida en habitacion y asset
//				TblPaquete paq = paqueteEnCuenta.getTblPaquete( ) ;
//				TblAsset eventoPaq = paq.getTblAsset( ) ;
//				int tipoHabitacion = paq.getHabitacion( ) ;
//				// verifica si es del mismo
//				if( eventoPaq.getCveAsset( ) == evento.getCveAsset( ) && habitacion == tipoHabitacion )
//					// agrega
//					paquetesAsignados.add( paqueteEnCuenta ) ;
//			}
			
			// tamanio de paquetes asignados del mismo tipo
			int paquetesEnCuentaSize = paquetesAsignados.size( ) ;
			
			// en cao de no vacio
			if( paquetesEnCuenta != null && paquetesEnCuentaSize > 0 )
			{
				// convierte en arreglo del mismo tamanio
				TblCuentaPaquete[ ] countPaqs = new TblCuentaPaquete[ paquetesEnCuentaSize ] ;
				
				// convierte a un arreglo
				countPaqs = paquetesAsignados.toArray( countPaqs ) ;
				
				// ordena
				Arrays.sort( countPaqs , new Comparator< TblCuentaPaquete >( ) {
					public int compare( TblCuentaPaquete p1 , TblCuentaPaquete p2 )
					{
						// toma los datos
						int fondeado1 = p1.getTblPaquete( ).getFondeado( ) ;
						int facturado1 = p1.getTblPaquete( ).getFacturadoA( ) ;
						int fondeado2 = p2.getTblPaquete( ).getFondeado( ) ;
						int facturado2 = p2.getTblPaquete( ).getFacturadoA( ) ;
						
						int suma1 = 0 ;
						int suma2 = 0 ;
						
						// en caos de que fondeado sea local y facturado sea local
						if( fondeado1 == 1 && facturado1 ==1 )
							suma1 = 2 ;
						if( fondeado1 == 1 && facturado1 == 2 )
							suma1 = 3 ;
						if( fondeado1 == 2 && facturado1 == 1 )
							suma1 = 4 ;
						if( fondeado1 == 2 && facturado1 == 2 )
							suma1 = 5 ;
						if( fondeado2 == 1 && facturado2 ==1 )
							suma2 = 2 ;
						if( fondeado2 == 1 && facturado2 == 2 )
							suma2 = 3 ;
						if( fondeado2 == 2 && facturado2 == 1 )
							suma2 = 4 ;
						if( fondeado2 == 2 && facturado2 == 2 )
							suma2 = 5 ;
						
						// regresa diferencia
						return suma1 - suma2 ;
					}
				} ) ;
				
				// recorre los paquetes
				for( TblCuentaPaquete paq : countPaqs )
				{
					System.out.println( paq.getTblPaquete( ).getHabitacion( ) + " - " + paq.getTblPaquete( ).getFondeado( ) + " - " + paq.getTblPaquete( ).getFacturadoA( ) ) ;
				}
				
				// una vez ordenados recorre los primeros
				for( int j = 0 ; j < paquetesEnCuentaSize && j < regresados[ i ] ; j++ )
				{
					// procesa el regreso del paquete
					// toma el TblCuentaPaquete
					TblCuentaPaquete paqueteARegresar = countPaqs[ j ] ;
					
					// toma el paquete
					TblPaquete paq = paqueteARegresar.getTblPaquete( ) ;
					
					// verifica el TblTipoCuentaPaquete
					List< TblTipoCuentaPaquete > tipoCuentasDePaquete = paq.getTblTipoCuentaPaquetes( ) ;
					
					// toma el referente
					TblTipoCuentaPaquete tipoCuentaDePaquete = null ;
					
					// recorre tipoCuentasDePaquete
					for( TblTipoCuentaPaquete tcp : tipoCuentasDePaquete )
					{
						// en caso de que sea del mismo tipo de cuenta
						if( tcp.getTblTipoCuenta( ).getCveTipoCuenta( ) == cuenta.getTblTipoCuenta( ).getCveTipoCuenta( ) )
						{
							tipoCuentaDePaquete = tcp ;
							
							break ;
						}
					}// termina el for
					
					try
					{
						// modifica
						MasterCardDAO.regresarPaquete( paqueteARegresar , tipoCuentaDePaquete ) ;
					}catch( MasterCardException mce )
					{
                                            MasterCardDAO.closeEntityManager( ) ;
						user.setMessageError( mce.getSingularMessage( ) ) ;
						
						user.setNextWorkArea( "/WEB-INF/pages/WorkArea/SolicitarPaqueteError.jsp" ) ;
						
						return mapping.findForward( "success" ) ;
					}
					
				}// termina el for
			}// termin el if de paquetesCuentaSize > 0
		}// termina el for d paqueteSolicitarListaSize
		
		
		
		// recorre los PaqueteSolicitar para procesar los solicitados
		for( int i = 0 ; i < paqueteSolicitarListaSize ; i++ )
		{
			// verifica que haya regresados
			if( solicitados[ i ] < 1 )
				// siuiente
				continue ;
			
			PaqueteSolicitar paqSol = paqueteSolicitarLista.get( i ) ;
			
			// datos
			// toma la cuenta
			int cveCuenta = paqSol.getCveCuenta( ) ;
			TblCuenta cuenta = MasterCardDAO.findCountById( cveCuenta ) ;
			
			TblAsset evento = paqSol.getEvento( ) ;
			int habitacion = paqSol.getTipoHabitacion( ) ;
			
			// en caos de null
			if( cuenta == null )
			{
                            MasterCardDAO.closeEntityManager( ) ;
				user.setMessageError( MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.tipocuenta.solicitarpaquetes.CountNotExist" ) ) ;
				
				user.setNextWorkArea( "/WEB-INF/pages/WorkArea/SolicitarPaqueteError.jsp" ) ;
				
				return mapping.findForward( "success" ) ;
			}
			
			// paquetes asignados al tipo de cuenta
			List< TblTipoCuentaPaquete > paquetesEnTipoCuenta = paqSol.getPaquetesAsignadosPorTipoCuenta( cuenta.getTblTipoCuenta( ).getCveTipoCuenta( ) ) ;
			
			// toma los paquetes de dicha cuenta
			List< TblTipoCuentaPaquete > paquetesEnTipoCuentaSinAsignar = new ArrayList< TblTipoCuentaPaquete >( ) ;
			
			// recorre los paquetes
			for( TblTipoCuentaPaquete paqueteEnTipoCuenta : paquetesEnTipoCuenta )
			{
				// en caso de que no este asignado
				if( paqueteEnTipoCuenta.getBandera( ) == 1 )
					// agrega
					paquetesEnTipoCuentaSinAsignar.add( paqueteEnTipoCuenta ) ;
			}
			
			// tamanio de paquetes asignados del mismo tipo
			int paquetesEnTipoCuentaSize = paquetesEnTipoCuentaSinAsignar.size( ) ;
			
			// en cao de no vacio
			if( paquetesEnTipoCuentaSinAsignar != null && paquetesEnTipoCuentaSize > 0 )
			{
				// convierte en arreglo del mismo tamanio
				TblTipoCuentaPaquete[ ] countPaqs = new TblTipoCuentaPaquete[ paquetesEnTipoCuentaSize ] ;
				
				// convierte a un arreglo
				countPaqs = paquetesEnTipoCuentaSinAsignar.toArray( countPaqs ) ;
				
				// ordena
				Arrays.sort( countPaqs , new Comparator< TblTipoCuentaPaquete >( ) {
					public int compare( TblTipoCuentaPaquete p1 , TblTipoCuentaPaquete p2 )
					{
						// toma los datos
						int fondeado1 = p1.getTblPaquete( ).getFondeado( ) ;
						int facturado1 = p1.getTblPaquete( ).getFacturadoA( ) ;
						int fondeado2 = p2.getTblPaquete( ).getFondeado( ) ;
						int facturado2 = p2.getTblPaquete( ).getFacturadoA( ) ;
						
						int suma1 = 0 ;
						int suma2 = 0 ;
						
						// en caos de que fondeado sea local y facturado sea local
						if( fondeado1 == 1 && facturado1 ==1 )
							suma1 = 2 ;
						if( fondeado1 == 1 && facturado1 == 2 )
							suma1 = 3 ;
						if( fondeado1 == 2 && facturado1 == 1 )
							suma1 = 4 ;
						if( fondeado1 == 2 && facturado1 == 2 )
							suma1 = 5 ;
						if( fondeado2 == 1 && facturado2 ==1 )
							suma2 = 2 ;
						if( fondeado2 == 1 && facturado2 == 2 )
							suma2 = 3 ;
						if( fondeado2 == 2 && facturado2 == 1 )
							suma2 = 4 ;
						if( fondeado2 == 2 && facturado2 == 2 )
							suma2 = 5 ;
						
						// regresa diferencia
						return suma2 - suma1 ;
					}
				} ) ;
				
				// recorre los paquetes
//				for( TblTipoCuentaPaquete paq : countPaqs )
//				{
//					System.out.println( paq.getTblPaquete( ).getHabitacion( ) + " - " + paq.getTblPaquete( ).getFondeado( ) + " - " + paq.getTblPaquete( ).getFacturadoA( ) ) ;
//				}
				
				int tipoHabitacion = -1 ;
				TblAsset asset = null ;
				
				// una vez ordenados recorre los primeros
				for( int j = 0 ; j < paquetesEnTipoCuentaSize && j < solicitados[ i ] ; j++ )
				{
					// procesa la solicitud del paquete
					// toma el TblCuentaPaquete
					TblTipoCuentaPaquete paqueteASolicitar = countPaqs[ j ] ;
					
					// toma el paquete
					TblPaquete paq = paqueteASolicitar.getTblPaquete( ) ;
					
					tipoHabitacion = paq.getHabitacion( ) ;
					asset = paq.getTblAsset( ) ;
					
					//////////////////////////////////
					// verifica el TblTipoCuentaPaquete
					List< TblTipoCuentaPaquete > tipoCuentasDePaquete = paq.getTblTipoCuentaPaquetes( ) ;
					
					// toma el referente
					TblTipoCuentaPaquete tipoCuentaDePaquete = null ;
					
					// recorre tipoCuentasDePaquete
					for( TblTipoCuentaPaquete tcp : tipoCuentasDePaquete )
					{
						// en caso de que sea del mismo tipo de cuenta
						if( tcp.getTblTipoCuenta( ).getCveTipoCuenta( ) == cuenta.getTblTipoCuenta( ).getCveTipoCuenta( ) )
						{
							tipoCuentaDePaquete = tcp ;
							
							break ;
						}
					}// termina el for
					
					try
					{
						// modifica
						MasterCardDAO.iniciarSolicitarPaquete( cuenta , paqueteASolicitar , paq , user.getTblUsuario( ) ) ;
					}catch( MasterCardException mce )
					{
                                            MasterCardDAO.closeEntityManager( ) ;
						user.setMessageError( mce.getSingularMessage( ) ) ;
						
						user.setNextWorkArea( "/WEB-INF/pages/WorkArea/SolicitarPaqueteError.jsp" ) ;
						
						return mapping.findForward( "success" ) ;
					}
					
				}// termina el for
				
				try
				{
					// dispara las alertas
					NotificationUtil.throwNotificationTypeRequestPackage( solicitados[ i ] , tipoHabitacion , asset , user ) ;
				}catch( Exception e )
				{
					e.printStackTrace( ) ;
				}
				
			}// termin el if de paquetesCuentaSize > 0
			
		}// termina el for d paqueteSolicitarListaSize
		
		// en caso de que se cumpla, guarda el WorkArea
		//user.setNextWorkArea( "/SolicitarPaqueteIn.do" ) ;
                
                // modifico para Sustituir pantalla Alex                
                user.setNextWorkArea( "/ListarPaquetesAsignadosIn.do" ) ;
		
                MasterCardDAO.closeEntityManager( ) ;
	  	return mapping.findForward( "success" ) ;
	}
	
}
